package research;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.store.SimpleFSDirectory;
import org.apache.lucene.util.Version;
import org.apache.sling.commons.json.JSONArray;
import org.apache.sling.commons.json.JSONObject;

public class Driver {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		try{
			//System.setProperty("wordnet.database.dir", "/media/EA4A364A4A361433/Dev/Dev_WS/DataMiningProject/WordNet-3.0/dict/");
			System.setProperty("wordnet.database.dir", "E:/Dev/Dev_WS/DataMiningProject/WordNet-3.0/dict/");			
			//generateTrainedModel();
			System.out.print("Enter search query: ");
			BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in));
			System.out.println("Predicted click: "+predict(bfr.readLine()));
		}catch(Exception e){
			e.printStackTrace();
		}
	}

	private static void generateTrainedModel() {
		try{
			//FileWriter writer = new FileWriter("/media/EA4A364A4A361433/Dev/Dev_WS/DataMiningProject/model.dat");
			FileWriter writer = new FileWriter("E:/Dev/Dev_WS/DataMiningProject/model.dat");

			Model model = new Model();
			model.readCSV();
			BipartiteGraph bGraph = model.generateBipartiteGraph();
			bGraph = model.agglomerativeClustering(bGraph);

			JSONObject jsonObjects = new JSONObject();
			JSONArray jsonArray = new JSONArray();
			int jsonIndex = 0;
			int simIndex;
			List<Edge> edges = bGraph.getForwardEdges(); 
			for(Edge edge:edges){
				Vertex source = edge.getSource();
				Vertex destination = edge.getDestination();

				JSONObject jsonObject = new JSONObject();
				jsonObject.put("source",source);
				jsonObject.put("destination",destination);
				jsonObject.put("timeTaken", edge.getWeight());
				JSONArray simVerticesJSONArr = new JSONArray();
				List<Vertex> simVertices = source.getSimilarVertices();
				if(simVertices!=null){
					simIndex = 0;
					for(Vertex simVertex:simVertices){
						simVerticesJSONArr.put(simIndex,simVertex);
						simIndex++;
					}
				}
				jsonObject.put("simSourceVertices", simVerticesJSONArr);

				simVerticesJSONArr = new JSONArray();
				simVertices = destination.getSimilarVertices();
				if(simVertices!=null){
					simIndex = 0;
					for(Vertex simVertex:simVertices){
						JSONObject simDest = new JSONObject();
						simDest.put("destination", simVertex);
						simDest.put("timeTaken", simVertex.getTs());

						simVerticesJSONArr.put(simIndex,simDest);
						simIndex++;
					}
				}
				jsonObject.put("simDestinationVertices", simVerticesJSONArr);

				jsonArray.put(jsonIndex,jsonObject);
				jsonIndex++;
			}

			if(jsonArray.length()>0){
				jsonObjects.put("clusters", jsonArray);
				writer.write(jsonObjects.toString());
				writer.write("\n");
				writer.close();
			}

		}catch(Exception e){
			e.printStackTrace();
		}

	}

	public static String predict(String query){
		String predictedClick = "";

		String[] qArr = query.split(" ");
		Set<String> qSet = buildTermVector(qArr, new HashSet<String>());

		float maxTermVectorSimilarity = 0;
		long minTimeTaken;

		Set<String> rSet;
		//File model = new File("/media/EA4A364A4A361433/Dev/Dev_WS/DataMiningProject/model.dat");
		File model = new File("E:/Dev/Dev_WS/DataMiningProject/model.dat");
		try{
			BufferedReader bfr = new BufferedReader(new InputStreamReader(new FileInputStream(model)));
			String json = "";
			while((json = bfr.readLine())!=null){
				JSONObject jsonObj = new JSONObject(json.trim());
				JSONArray clusters = jsonObj.getJSONArray("clusters");
				for(int i=0; i<clusters.length(); i++){
					JSONObject edge = clusters.getJSONObject(i);
					rSet = new HashSet<String>();

					Set<String> tmpSet = new HashSet<String>();
					String source = edge.getString("source");
					tmpSet.add(source);

					JSONArray simSources = edge.getJSONArray("simSourceVertices");
					for(int j=0; j<simSources.length(); j++){
						tmpSet.add((String)simSources.get(j));
					}

					for(String srcQuery:tmpSet){
						rSet = buildTermVector(srcQuery.split(" "), rSet);
					}

					float termVectorSimilarity = Model.computerTermVectorSimilarity(qSet,rSet);
					if(termVectorSimilarity > maxTermVectorSimilarity){
						maxTermVectorSimilarity = termVectorSimilarity;
						predictedClick = edge.getString("destination");
						minTimeTaken = edge.getLong("timeTaken");

						JSONArray simDestinations = edge.getJSONArray("simDestinationVertices");
						for(int j=0; j<simDestinations.length(); j++){
							JSONObject simDest = simDestinations.getJSONObject(j);
							long simDestTimeTaken = simDest.getLong("timeTaken");

							if(simDestTimeTaken<minTimeTaken){
								minTimeTaken = simDestTimeTaken;
								predictedClick = simDest.getString("destination");
							}
						}						

					}

				}
			}

			SimpleFSDirectory index = new SimpleFSDirectory(new File("D:/product_data/sku_name_mapping_index"));
			StandardAnalyzer analyzer = new StandardAnalyzer(Version.LUCENE_36);

			IndexReader reader = IndexReader.open(index);
			IndexSearcher searcher = new IndexSearcher(reader);

			Query q = new QueryParser(Version.LUCENE_36, "sku", analyzer).parse(predictedClick.trim());
			ScoreDoc[] hits = LuceneIndexManager.searchLuceneIndex(q, searcher);

			if(hits.length>0){
				int docId = hits[0].doc;
				Document d = searcher.doc(docId);
				predictedClick = d.get("name");
			}

		}catch(Exception e){
			e.printStackTrace();
		}

		return predictedClick;
	}

	private static Set<String> buildTermVector(String[] termArr, Set<String> termVector) {
		Set<String> simWords;
		for(String q:termArr){
			termVector.add(q.toLowerCase());
			simWords = Model.getSimilarWords(q);
			for(String simWord:simWords){
				termVector.add(simWord.toLowerCase());
			}
		}
		return termVector;
	}


}
